package com.linkoog.devtools.generate.method_creater.actions;

import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.file.impl.JavaFileManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.linkoog.devtools.generate.method_creater.dialog.ControllerMethodDialog;
import org.jetbrains.annotations.NotNull;

public class ControllerMethodAction extends AnAction {

    private static NotificationGroup notificationGroup;
    static {
        notificationGroup = new NotificationGroup("DevTools.CodeGen.ControllerMethod",  NotificationDisplayType.BALLOON);
    }

    private static final String Controller = "org.springframework.stereotype.Controller";
    private static final String RestController = "org.springframework.web.bind.annotation.RestController";

    @Override
    public void actionPerformed(@NotNull AnActionEvent event) {
        Project project = event.getProject();
        if (project == null) return;

        Module module = event.getData(LangDataKeys.MODULE);
        if (module == null) return;

        PsiFile psiFile = event.getData(LangDataKeys.PSI_FILE);
        if (psiFile == null) return;

        Editor editor = event.getData(PlatformDataKeys.EDITOR);
        if (editor == null) return;

        CaretModel caretModel = editor.getCaretModel();
        LogicalPosition logicalPosition = caretModel.getLogicalPosition();

        PsiElement element = psiFile.findElementAt(caretModel.getOffset());
        PsiMethod selectedMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
        PsiElement offsetElement = selectedMethod != null ? selectedMethod : element;

        PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
        if (psiClass == null) return;

        //controller的错误提示
        if (!(psiClass.hasAnnotation(Controller) || psiClass.hasAnnotation(RestController))){
            showErrorMessage(project,"该class不是controller类");
            return;
        }

        PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);

        ControllerMethodDialog dialog = new ControllerMethodDialog(project, controllerMethodVo -> {
            controllerMethodVo.setModelName(parseJavaModule(psiClass));

            WriteCommandAction.runWriteCommandAction(project, () -> {
                PsiMethod builder = elementFactory.createMethodFromText(controllerMethodVo.getMethodText(), psiClass);
                psiClass.addAfter(builder, offsetElement);
                if (psiFile instanceof PsiJavaFile){
                    PsiJavaFile psiJavaFile = (PsiJavaFile)psiFile;
                    JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
                    styleManager.optimizeImports(psiFile);
                    styleManager.shortenClassReferences(psiFile);

                    JavaFileManager javaFileManager = JavaFileManager.getInstance(project);
                    for (String className : controllerMethodVo.getImportSet()) {
                        PsiClass importClass = javaFileManager.findClass(className, GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false));
                        if (importClass != null){
                            styleManager.addImport(psiJavaFile, importClass);
                        }
                    }
                }
            });
        });
        dialog.showAndGet();
    }



    @Override
    public void update(@NotNull AnActionEvent event) {
        Project project = event.getProject();
        PsiFile psiFile = event.getData(LangDataKeys.PSI_FILE);
        Editor editor = event.getData(PlatformDataKeys.EDITOR);
        if (project == null || psiFile == null || editor == null) {
            event.getPresentation().setVisible(false);
            return;
        }

        PsiElement element = psiFile.findElementAt(editor.getCaretModel().getOffset());
        PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
        if (!psiFile.isDirectory() && psiClass != null) {
            event.getPresentation().setVisible(true);
        } else {
            event.getPresentation().setVisible(false);
        }
    }

    private String parseJavaModule(PsiClass psiClass){
        String className = psiClass.getName();
        if ("Controller".equals(className) || !className.endsWith("Controller")){
            return fristLowerChar(className);
        }
        className = className.substring(0, className.length() - "Controller".length());
        return fristLowerChar(className);
    }

    private String fristLowerChar(String name){
        if (name.length() == 1){
            return name.toLowerCase();
        } else {
            return name.substring(0,1).toLowerCase() + name.substring(1);
        }
    }

    private void showErrorMessage(Project project, String errorMsg) {
        Notification error = notificationGroup.createNotification(errorMsg, NotificationType.INFORMATION);
        Notifications.Bus.notifyAndHide(error, project);
    }

}
